//
// CrackConfReader
//
// Copyright (C) jextra.net.
//
//  This file is part of the Crack build system.
//
//  The Crack build system is free software; you can redistribute it 
//  and/or modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  The Crack build system is distributed in the hope that it will be 
//  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with the Crack build system; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
//  02111-1307 USA.
//

package net.jextra.crack.core;

import java.lang.reflect.*;
import net.jextra.crack.updater.*;
import org.xml.sax.*;

/**
 * <p>
 * Reads the crack configuration XML file (conf/crack-conf.xml).
 * </p>
 */
public class CrackConfReader extends XMLSAXReader
{
    // ============================================================
    // Enums
    // ============================================================

    public enum State
    {
        crackConf( "crack-conf" ), 
        updater( "updater" );

        private String tag;

        State( String tag )
        {
            this.tag = tag;
        }

        public String tag()
        {
            return tag;
        }
    }

    // ============================================================
    // Fields
    // ============================================================

    private CrackUpdaterParams updaterParams;
    private CrackUpdater updater;

    // ============================================================
    // Constructors
    // ============================================================

    public CrackConfReader()
    {
        updater = null;
    }

    // ============================================================
    // Methods
    // ============================================================

    // ----------
    // public
    // ----------

    public CrackUpdater getUpdater()
    {
        return updater;
    }

    // ----------
    // protected
    // ----------

    @Override
    protected void startDocument()
        throws Exception
    {
    }

    @Override
    protected String startElement( String stateString, String uri, String tagName, String name,
        Attributes atts )
        throws Exception
    {
        State state = getState( stateString );
        State newState = null;

        if ( tagName.equalsIgnoreCase( State.crackConf.tag() ) )
        {
            newState = State.crackConf;
        }
        else if ( state == State.crackConf && tagName.equalsIgnoreCase( State.updater.tag() ) )
        {
            newState = State.updater;

            updaterParams = new CrackUpdaterParams( tagName );
            for ( int i = 0; i < atts.getLength(); i++ )
            {
                updaterParams.addAttribute( atts.getQName( i ), atts.getValue( i ) );
            }
        }

        return newState == null ? null : newState.name();
    }

    @Override
    protected void characters( String stateString, char[] value, int offset, int count )
        throws Exception
    {
    }

    @Override
    protected void endElement( String stateString, String uri, String tagName, String name )
        throws Exception
    {
        State state = getState( stateString );

        if ( state == State.updater )
        {
            updater = createUpdater( updaterParams );
        }
    }

    @Override
    protected void endDocument()
        throws Exception
    {
    }

    // ----------
    // private
    // ----------

    private State getState( String stateString )
    {
        return stateString == null ? null : State.valueOf( stateString );
    }

    @SuppressWarnings( "unchecked" )
    private CrackUpdater createUpdater( CrackUpdaterParams rootNode )
        throws Exception
    {
        Class<CrackUpdater> updaterClass = ( Class<CrackUpdater> ) Class.forName(
            rootNode.getAttribute( "class" ) );

        Constructor<CrackUpdater> cons = updaterClass.getDeclaredConstructor();
        cons.setAccessible( true );
        CrackUpdater updater = cons.newInstance();
        updater.init( rootNode );

        return updater;
    }
}

